#ifndef _BGSEGM_MOG_H_
#define _BGSEGM_MOG_H_

#include <cv.h>
//#include <cxcore.h>
#include "bgsegm.h"

#if defined WIN32 || defined _WIN32
#define CV_CDECL __cdecl
#define CV_STDCALL __stdcall
#else
#define CV_CDECL
#define CV_STDCALL
#endif

/* 
Interface of Gaussian mixture algorithm

"An improved adaptive background mixture model for real-time tracking with shadow detection"
P. KadewTraKuPong and R. Bowden,
Proc. 2nd European Workshp on Advanced Video-Based Surveillance Systems, 2001."
http://personal.ee.surrey.ac.uk/Personal/R.Bowden/publications/avbs01/avbs01.pdf
*/

/* Note:  "MOG" == "Mixture Of Gaussians": */

#define CV_BGFG_MOG_MAX_NGAUSSIANS 500

/* default parameters of gaussian background detection algorithm */
#define CV_BGFG_MOG_BACKGROUND_THRESHOLD		0.7     /* threshold sum of weights for background test */
#define CV_BGFG_MOG_STD_THRESHOLD						2.5     /* lambda=2.5 is 99% */
#define CV_BGFG_MOG_WINDOW_SIZE							200     /* Learning rate; alpha = 1/CV_GBG_WINDOW_SIZE */
#define CV_BGFG_MOG_NGAUSSIANS							5         /* = K = number of Gaussians in mixture */
#define CV_BGFG_MOG_NSHADOWGAUSSIANS				3         //the number of the shadow gaussians in mixture  GMSM
#define CV_BGFG_MOG_WEIGHT_INIT							0.05
#define CV_BGFG_MOG_SIGMA_INIT								30
#define CV_BGFG_MOG_MINAREA									15.f
#define CV_BGFG_MOG_NCOLORS									3
#define CV_BGFG_MOG_NOICESIGMA_INIT                    15 //CV_BGFG_MOG_SIGMA_INIT * 0.5

// defualt parameters of shadow gaussian detection 
#define  CV_SDW_MOG_NSHADOWGAUSSIANS               3       //the number of the shadow gaussians in mixture  GMSM
#define  CV_SDW_MOG_WEIGHT_INIT                            0.05  //the weight of init gaussians
#define  CV_SDW_MOG_SIGMA_INIT                               30    
#define  CV_SDW_MOG_WINDOW_SIZE                           200
#define  CV_SDW_MOG_SHADOW_THRESHOLD                 0.7
#define  CV_SDW_MOG_STD_THRESHOLD                         2.5
#define  CV_SDW_MOG_BCD_THRESHOLD                         0.8
#define  CV_SDW_MOG_NOICESIGMA_INIT                      15 //CV_SDW_MOG_SIGMA_INIT * .05

#define CV_BG_MODEL_MOG		1			/* "Mixture of Gaussians".	*/

typedef struct CvGaussShadowStatModelParams  //shadow guassians params
{
	int			iShadowGauss;
	int			iShadowWinSize;
	double	dwShThreshold;
	double	dwStdThreshold;
	double  dwWeightInit;
	double  dwVarianceInit;
	double dwNocieSigmaInit;

	double  dwBCDThreshold;
}CvGaussShadowStatModelParams;

typedef struct CvGaussBGStatModelParams //background gaussian params
{    
	int     win_size;               /* = 1/alpha */
	int     n_bggauss;
	double  bg_threshold;
	double  std_threshold;
	double  minArea;
	double  weight_init;
	double  variance_init;
	double  nocie_sigma_init;
}CvGaussBGStatModelParams;

typedef struct CvGaussBGValues
{
	int         match_sum;
	double      weight;
	double      variance[CV_BGFG_MOG_NCOLORS];
	double      mean[CV_BGFG_MOG_NCOLORS];
} CvGaussBGValues;

typedef struct CvGaussBGPoint
{
	CvGaussBGValues* g_values;
} CvGaussBGPoint;


typedef void (CV_CDECL * CvReleaseBGStatModel)( struct CvBGStatModel** bg_model );
typedef int (CV_CDECL * CvUpdateBGStatModel)( IplImage* curr_frame, struct CvBGStatModel* bg_model,double learningRate, double learningRateShadow );

#define CV_BG_STAT_MODEL_FIELDS()																	\
	int									type; /*type of BG model*/											\
	CvReleaseBGStatModel	release;																			\
	CvUpdateBGStatModel	update;																			\
	IplImage*       background;   /*8UC3 reference background image*/						\
	IplImage*       foreground;   /*8UC1 foreground image*/										\
	IplImage*       UpdateMask; /*8UC1 UpdateMask image, Added by xcp*/				\
	IplImage**     layers;       /*8UC3 reference background image, can be null */		\
	int							layer_count;			/* can be zero */										\
	CvMemStorage*    storage;      /*storage for foreground_regions*/						\
	CvSeq*				   foreground_regions /*foreground object contours*/

typedef struct CvGaussBGModel
{
	CV_BG_STAT_MODEL_FIELDS();
	CvGaussBGStatModelParams   BgParams;
	CvGaussShadowStatModelParams ShadowParams;
	CvGaussBGPoint*            g_point;    
	int                        countFrames;
} CvGaussBGModel;

struct CvBGStatModel;


typedef struct CvBGStatModel
{
	CV_BG_STAT_MODEL_FIELDS();
} CvBGStatModel;


 CvBGStatModel* cvCreateGaussianBGModel( IplImage* first_frame, CvGaussBGStatModelParams* BgParameters = NULL,CvGaussShadowStatModelParams * ShadowParams = NULL);

// Releases memory used by BGStatModel
void  cvReleaseBGStatModel( CvBGStatModel** bg_model );

// Updates statistical model and returns number of found foreground regions
int cvUpdateBGStatModel( IplImage* current_frame, CvBGStatModel*  bg_model, double learningRate = -1,double learningRateShadow = 0);

#endif